import StrTo from "../utils/StrTo";

var crypto = require('crypto');
import  RD from '../basics/Phere.js'
import Block from "../basics/Block.js";
import  Row from '../basics/Row.js'
import  Rx from "./Rx.js" ;
//
// import {
//     BASE_INDEX,
//     WAN_INDEX,
//     DEFINE_INDEX
// }   from "./IndexType.js"
/**
 * 链包
 * 一个链表通常包括,一万个wan
 *
 */

export default class Dx{

    /**
     * 第一个块是用来装载基本信息，
     * 比如，这个模块叫什么，
     * 目录起始块到结束块，（通常目录丢到最后）
     */
    constructor( ){
        let phere= new RD();
        this.rxList=[];
        this.rxs=new Map();
        this.rounds={"0":phere}
        this. contents=new RD();
        this.headRx=new Rx();
        this.tailRx=new Rx();

        this.headPhere=new RD();
        this.tailPhere=new RD();

    }

    searchFile(name){
        let id= this.contents.search(name)
        if(id==""){
            return null;
        }
        return this.rxs[id]
    }



    findHead(){
        return this.headRx;
    }

    findTail(){
        return this.tailRx;
    }
    saveHead(rx){
        this.headRx=rx;
    }
    saveTail(rx){
        this.tailRx=rx;
    }

    findContents(){
        return this.contents;
    }

    addDir(name){
        this.contents.addNode(name);
        return true
    }

    addFile(name,type,rx){
        let id= this.contents.addNode(name,type);
        this.rxs[id]=rx;
        return true
    }

    isDir(name){
        return true;
    }
    findFileType(){
        return "";
    }

    findFile(name){
        let id= this.contents.findId(name)
        return this.rxs[id]
    }

    saveFile(name,rx,dir,type){
        let id=    this.contents.findId(name)

        if(id==null){
            id= this.contents.addNode(name,type);
        }
        this.rxs[id]=rx;
        return true
    }

    cd(dirName){
        this.contents.cd(dirName);
    }
    findCurrentDir(){
        return  this.contents.findCurrentDir();
    }

    del(name){
        let ids =  this.contents.del(name);
        for(let i=0;i<ids.length;i++){
            delete this.rxs[ids[i]];
        }
    }
    findDir(){
        this.contents.findDir();
    }


    /**
     *  加载 数据
     * @param data
     */
    loadData(data){
        let _this=this;
        let length=0;
        this.rxs=new Map();
        let buff= new Uint8Array(data);

        let rxs=Rx.buffToRxs(buff);

        let headRx=rxs[0];
        let headPhere =new RD();
        let headBuff=headRx.outData()
        headPhere.loadData( headBuff);
        let headDlock= headPhere.find(2)


        /**
         * 加载目录
         * @type {Int32Array | Uint8Array | Int8Array | Int16Array | Uint16Array | Uint32Array | any}
         */
        let contentsRow=  headDlock.find(1)
        let contentsRxs=rxs.slice(parseInt(contentsRow.find(1)),parseInt(contentsRow.find(1))  +parseInt(contentsRow.find(4)))
        let contentsBuff= Rx.rxsToBuff(contentsRxs);
        this. contents.loadData(contentsBuff)

        /**
         * 加载索引
         * @type {Int32Array | Uint8Array | Int8Array | Int16Array | Uint16Array | Uint32Array | any}
         */


        let indexRow= headDlock.find(2)
        let indexRxs=rxs.slice(parseInt(indexRow.find(1)),parseInt(indexRow.find(1))  +parseInt(indexRow.find(4)))
        let indexBuff= Rx.rxsToBuff(indexRxs);
        let indexPhere =new RD();
        indexPhere.loadData( indexBuff);
        let indexBlock= indexPhere.find(2)

        /**
         * 加载数据
         */
        for(let i=0;i< indexBlock.list.length;i++){
            let row=indexBlock.list[i];
            let dataRxs= rxs.slice(row.find(2),    parseInt(row.find(2))  +parseInt(row.find(4)))
            let rxbuff =  Rx.rxsToBuff(dataRxs);
            let rx=new Rx();
            rx.loadData(rxbuff);
            this.rxs[row.find(1)] =rx;
        }
        this.headRx=headRx;
        this.tailRx=rxs[10000-1]
        this.rxList=rxs.slice(1,   10000-1)
    }


    /**
     * 获取全部数据
     * @returns {uint8array[]|*[]}
     */
    outData(){

        this.calculateIndex();
        let resRxs=[this.headRx,...this.rxList,this.tailRx]
        /**
         * 转换成 buff格式
         */
        let resBuff=  Rx.rxsToBuff(resRxs)
        return resBuff;
    }

    /**
     * 创建索引
     */
    calculateIndex(){
        let rxs=this.rxs;
        let indexPhere =new RD();
        let haedPhere=new RD()
        let block =new Block();
        let headBlock =new Block();
        let pathrx=Rx.findRx();
        let headrx=Rx.findRx();
        let indexRx=Rx.findRx();
        let resList=[];
        /**
         * 查找临时文件里面有没有内容。
         * 如果有  从文件里面直接导出数据；
         * 如果 没有从list里面读取文件。
         */
        let resListLength=1;

        for(var key in rxs){
            let rx=rxs[key]
            resList.push(rx)
            block.addRow(new Row(key, resListLength,rx.findLength()))
            resListLength += rx.findLength();
        }
        indexPhere.addBlock(block)

        /**
         * 保存目录数据
         * 保存索引数据
         *
         */

        indexRx    .loadData(indexPhere.outData());
        pathrx.loadData(this.contents.outData())
        resList.push(pathrx)
        resList.push(indexRx)
        headBlock.addRow(new Row(resListLength,pathrx.findLength()))
        resListLength += pathrx.findLength();
        headBlock.addRow(new Row(resListLength,indexRx.findLength()))
        haedPhere.addBlock(headBlock);
        headrx.loadData(haedPhere.outData());
        this.headRx=headrx;

        /**
         * 对齐
         * 输出数据
         * @type {Rx}
         */
        let teml=new Rx();
        for(let i=resListLength;i<10000-2;i++){
            resList.push(teml)
        }
        this.rxList=resList;
    }



    /**
     * 创建编辑头
     */
    saveHeadRow(a,b,c,name){
        this.headPhere.index=3
        this.headPhere.saveRow(a,b,c,name)
    }

    /**
     * 创建编辑尾
     */
    saveTailRow(a,b,c,name){
        this.headPhere.index=3
       this.tailPhere.saveRow(a,b,c,name)

    }

    delHeadRow(name){
        this.headPhere.index=3
        this.headPhere.delRow(name)
    }
    delTailRow(name){
        this.headPhere.index=3
        this.tailPhere.delRow(name)
    }



    /**
     * 创建hash值
     */
    calculateHash(){


        var hash = crypto.createHash('sha256');// sha256或者md5

        let resRxs=[this.headRx,...this.rxList]
        /**
         * 转换成 buff格式
         */
        let resBuff=  Rx.rxsToBuff(resRxs)
        hash.update(resBuff);

        var res = hash.digest('hex');
        var resnum=StrTo.utf8ToNum(res)
        return resnum;
    }

    /**
     * 验证程序
     * @returns {boolean}
     */
    isValidHash () {
        let newHash= this.calculateHash();
        let blockHash=this.findHeadRow("哈希");

        if (blockHash[0] !== newHash) {
            console.log(`❌  哈希无效: ${blockHash} ${newBlock.hash}`)
            return false
        }
        return true
    }
}

